<script setup lang="ts">
import { ref, computed, nextTick, watch, onMounted } from 'vue';
import { useVirtualizer } from '@tanstack/vue-virtual';

const props = withDefaults(
  defineProps<{
    data: any[];
  }>(),
  {
    data: () => [],
  }
);

const parentRef = ref<HTMLElement | null>(null);
const measureElement = (el: any) => {
  if (!el) {
    return;
  }

  rowVirtualizer.value.measureElement(el);

  return undefined;
};

const rowVirtualizer = useVirtualizer({
  get count() {
    return props.data.length;
  },
  getScrollElement: () => parentRef.value,
  estimateSize: () => 26,
  overscan: 5,
});

const virtualRows = computed(() => rowVirtualizer.value.getVirtualItems());

const totalSize = computed(() => rowVirtualizer.value.getTotalSize());

watch(
  () => props.data,
  () => {
    nextTick(() => {
      rowVirtualizer.value.scrollToIndex(props.data.length - 1);
    });
  }
);

onMounted(() => {
  nextTick(() => {
    if (props.data.length === 0) return;
    rowVirtualizer.value.scrollToIndex(props.data.length - 1);
  });
});
</script>

<template>
  <div ref="parentRef" class="h-full overflow-auto contain-strict">
    <div
      :style="{ height: `${totalSize}px`, width: '100%', position: 'relative' }"
    >
      <div
        :style="{
          position: 'absolute',
          top: 0,
          left: 0,
          width: '100%',
          transform: `translateY(${virtualRows[0]?.start ?? 0}px)`,
        }"
      >
        <div
          v-for="virtualRow in virtualRows"
          :key="`${virtualRow.key}`"
          :data-index="virtualRow.index"
          :ref="measureElement"
        >
          <slot name="item" :row-data="props.data[virtualRow.index]"></slot>
        </div>
      </div>
    </div>
  </div>
</template>
